package com.caregiver.watch.common.utils.time;

import org.apache.commons.lang3.StringUtils;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoField;
import java.util.Date;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import static com.caregiver.watch.common.constant.NumberConstants.ONE;
import static com.caregiver.watch.common.constant.NumberConstants.SIXTY;
import static com.caregiver.watch.common.constant.NumberConstants.ZERO;

/**
 * 基于LocalDateTime的时间工具类
 * 提供日期时间处理相关功能
 */
public final class DateUtils {
    
    public static final DateTimeFormatter YYYY_MM_DD_HH_MM_SS = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    public static final DateTimeFormatter YYYY_MM_DD = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    public static final DateTimeFormatter YYYY_MM = new DateTimeFormatterBuilder()
                .appendPattern("yyyy-MM")
                .parseDefaulting(ChronoField.DAY_OF_MONTH, ONE)
                .toFormatter();
    public static final DateTimeFormatter YYYYMMDD = DateTimeFormatter.ofPattern("yyyyMMdd");
    public static final DateTimeFormatter YYYYMMDDHHMM = DateTimeFormatter.ofPattern("yyyyMMddHHmm");
    public static final DateTimeFormatter HH_MM = DateTimeFormatter.ofPattern("HH:mm");


    /**
     * 将秒数转换为LocalDateTime字符串格式
     * 
     * @param seconds 秒数（Unix时间戳）
     * @return 格式化后的日期时间字符串，格式为 "yyyy-MM-dd HH:mm:ss"
     */
    public static String convert2LocalDateTimeString(long seconds) {
        LocalDateTime localDateTime = LocalDateTime.ofEpochSecond(
                seconds, 0, ZoneOffset.UTC);
        return localDateTime.format(YYYY_MM_DD_HH_MM_SS);
    }

    /**
     * 将秒数转换为LocalDateTime对象
     * 
     * @param seconds 秒数（Unix时间戳）
     * @return LocalDateTime对象
     */
    public static LocalDateTime convert2LocalDateTime(long seconds) {
        return LocalDateTime.ofEpochSecond(seconds, 0, ZoneOffset.UTC);
    }

    /**
     * 将秒数转换为LocalDateTime对象，考虑时区
     * 
     * @param seconds 秒数（Unix时间戳）
     * @param zoneOffset 时区偏移
     * @return LocalDateTime对象
     */
    public static LocalDateTime convert2LocalDateTime(long seconds, ZoneOffset zoneOffset) {
        return LocalDateTime.ofEpochSecond(seconds, 0, zoneOffset);
    }

    /**
     * 验证字符串是否为有效的日期格式
     * 
     * @param dateStr 日期字符串
     * @return true-有效，false-无效
     */
    public static boolean isValidDate(String dateStr) {
        try {
            LocalDate.parse(dateStr, YYYY_MM_DD);
            return true;
        } catch (DateTimeParseException e) {
            return false;
        }
    }

    /**
     * 获取指定日期的前一天
     * 
     * @param dateStr 日期字符串，格式为 "yyyy-MM-dd"
     * @return 前一天的日期字符串
     */
    public static String getPreviousDay(String dateStr) {
        try {
            LocalDate date = LocalDate.parse(dateStr, YYYY_MM_DD);
            LocalDate previousDay = date.minusDays(1);
            return previousDay.format(YYYY_MM_DD);
        } catch (DateTimeParseException e) {
            return "";
        }
    }

    /**
     * 获取指定日期的后一天
     * 
     * @param dateStr 日期字符串，格式为 "yyyy-MM-dd"
     * @return 后一天的日期字符串
     */
    public static String getNextDay(String dateStr) {
        try {
            LocalDate date = LocalDate.parse(dateStr, YYYY_MM_DD);
            LocalDate nextDay = date.plusDays(1);
            return nextDay.format(YYYY_MM_DD);
        } catch (DateTimeParseException e) {
            return "";
        }
    }

    /**
     * 将LocalDateTime格式化为字符串
     * 
     * @param localDateTime LocalDateTime对象
     * @return 格式化后的日期时间字符串
     */
    public static String format(LocalDateTime localDateTime) {
        if (localDateTime == null) {
            return null;
        }
        return localDateTime.format(YYYY_MM_DD_HH_MM_SS);
    }

    /**
     * 将LocalTime格式化为字符串
     *
     * @param localTime localTime
     * @return 格式化后的日期时间字符串
     */
    public static String format(LocalTime localTime) {
        if (localTime == null) {
            return null;
        }
        return localTime.format(HH_MM);
    }

    /**
     * 将LocalDateTime格式化为字符串
     *
     * @param localDateTime LocalDateTime对象
     * @param formatter 日期时间格式
     * @return 格式化后的日期时间字符串
     */
    public static String format(LocalDateTime localDateTime, DateTimeFormatter formatter) {
        if (localDateTime == null) {
            return null;
        }
        return localDateTime.format(formatter);
    }

    /**
     * 将LocalDate格式化为字符串
     * 
     * @param localDate LocalDate对象
     * @return 格式化后的日期字符串
     */
    public static String format(LocalDate localDate) {
        if (localDate == null) {
            return null;
        }
        return localDate.format(YYYY_MM_DD);
    }


    /**
     * 将LocalDate格式化为字符串
     *
     * @param localDate LocalDate对象
     * @param formatter 日期格式
     * @return 格式化后的日期字符串
     */
    public static String format(LocalDate localDate, DateTimeFormatter formatter) {
        if (localDate == null) {
            return null;
        }
        return localDate.format(formatter);
    }

    /**
     * 解析日期时间字符串为LocalDateTime对象
     * 
     * @param dateTimeStr 日期时间字符串
     * @return LocalDateTime对象
     */
    public static LocalDateTime parseLocalDateTime(String dateTimeStr) {
        try {
            return LocalDateTime.parse(dateTimeStr, YYYY_MM_DD_HH_MM_SS);
        } catch (DateTimeParseException e) {
            return null;
        }
    }

    /**
     * 解析日期字符串为LocalDate对象
     * 
     * @param dateStr 日期字符串
     * @return LocalDate对象
     */
    public static LocalDate parseLocalDate(String dateStr) {
        try {
            return LocalDate.parse(dateStr, YYYY_MM_DD);
        } catch (DateTimeParseException e) {
            return null;
        }
    }

    /**
     * 解析日期字符串为LocalDate对象
     *
     * @param dateStr 日期字符串
     * @return LocalDate对象
     */
    public static LocalDateTime parseLocalDate(String dateStr, LocalTime localTime) {
        try {
            return LocalDateTime.of(LocalDate.parse(dateStr, YYYY_MM_DD), localTime);
        } catch (DateTimeParseException e) {
            return null;
        }
    }

    /**
     * 解析日期字符串为LocalDate对象
     *
     * @param dateStr 日期字符串
     * @return LocalDate对象
     */
    public static LocalDate parseLocalDate(String dateStr, DateTimeFormatter formatter) {
        if (StringUtils.isEmpty(dateStr)) {
            return null;
        }
        try {
            return LocalDate.parse(dateStr, formatter);
        } catch (DateTimeParseException e) {
            return null;
        }
    }

    /**
     * 获取当前时间的LocalDateTime对象
     * 
     * @return 当前时间的LocalDateTime对象
     */
    public static LocalDateTime now() {
        return LocalDateTime.now();
    }

    /**
     * 获取当前日期的LocalDate对象
     * 
     * @return 当前日期的LocalDate对象
     */
    public static LocalDate today() {
        return LocalDate.now();
    }

    /**
     * 将Date对象转换为LocalDateTime对象
     * 
     * @param date Date对象
     * @return LocalDateTime对象
     */
    public static LocalDateTime toLocalDateTime(Date date) {
        if (date == null) {
            return null;
        }
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
    }

    /**
     * 将LocalDateTime对象转换为Date对象
     * 
     * @param localDateTime LocalDateTime对象
     * @return Date对象
     */
    public static Date toDate(LocalDateTime localDateTime) {
        if (localDateTime == null) {
            return null;
        }
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 计算两个时间之间的时间
     */
    public static Integer getTimeBetween(String startTime, String endTime, TimeUnit timeUnit) {
        LocalDateTime start = parseLocalDateTime(startTime);
        LocalDateTime end = parseLocalDateTime(endTime);
        return getTimeBetween(start, end, timeUnit);
    }

    /**
     * 获取两个时间之间的时间
     */
    public static Integer getTimeBetween(LocalDateTime startTime, LocalDateTime endTime, TimeUnit timeUnit) {
        return (int) timeUnit.convert(Duration.between(startTime, endTime).toMillis(), TimeUnit.MILLISECONDS);
    }

    /**
     * 获取时间是今天分钟数
     */
    public static int getMinute(LocalDateTime recordedAt) {
        if (Objects.isNull(recordedAt)) {
            return ZERO;
        }
        return recordedAt.getHour() * SIXTY + recordedAt.getMinute();
    }

    /**
     * 解析时间
     */
    public static LocalTime parseTime(String time, DateTimeFormatter formatter) {
        if (StringUtils.isBlank(time)) {
            return null;
        }
        try {
            return LocalTime.parse(time, formatter);
        } catch (DateTimeParseException e) {
            return null;
        }
    }
}
